package gui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import core.algorithms.SearchParameters;
import core.course.TimeTable;
import core.experiment.Experiment;
import core.experiment.ExperimentResults;

public class ExperimentsContainer extends AbstractTableModel
{
	private static final long serialVersionUID = -2402905948272447233L;
	public static final String[] COLUMN_NAMES =
	{ 	"Total Runs", // 0
		"Algorithm",
		"Heuristic",
		"Initial State",
		"Random steps", // 4
		"Space seed Range",
		"Courses Num",
		"Draw limit",
		"Bound h. calls?", //8
		"Avg Course num", 
		"Avg final value", // 10
		"Max final value", // 11
		"Min final value", // 12
		"% finish all steps", //13
		"% Avg steps taken" // 14
		
	};
	
	private List<Experiment> m_ExperimentsList = Collections.synchronizedList(new ArrayList<Experiment>());
//	private Hashtable<ISearchAlgorithm<TimeTable>, Integer> m_SearchAlogToIndex;
	
	public List<Experiment> getSearchAlgorithmList()
	{
		return m_ExperimentsList;
	}

	@Override
	public Class<?> getColumnClass(int columnIndex)
	{
		switch(columnIndex)
		{
			case 0: return Integer.class; 	// total runs
			case 1: return String.class;	// algorithm name
			case 2: return String.class;	// heuristic method
			case 3: return String.class;	// initialState
			case 4: return Integer.class;	// randomSteps
			case 5: return String.class;	// space seed range
			case 6: return Integer.class;	// courses number
			case 7: return String.class;	// draw limit
			case 8:	return Boolean.class;	// bound heuristic calls
			
			// results
			case 9: return String.class;	// average course number
			case 10: return String.class;	// average final value
			case 11: return String.class;	// maximum final value
			case 12: return String.class;	// minimum final value
			case 13: return String.class;	// percentage finish all steps
			case 14: return String.class;	// average total steps taken
		}
		return null;
	}
	@Override
	public Object getValueAt(int rowIndex, int columnIndex)
	{
		if (rowIndex < m_ExperimentsList.size())
		{
			Experiment experiment = m_ExperimentsList.get(rowIndex);
			boolean experimentFinished = experiment.isFinished();
			SearchParameters<TimeTable> searchParameters = experiment.getSearchParameters();
			ExperimentResults searchResults = (experimentFinished ? experiment.getSearchResults() : new ExperimentResults());
			switch(columnIndex)
			{
				// experiment parameters
				case 0: return rowIndex + 1;
				case 1: return experiment.getAlgorithmName();
				case 2: return searchParameters.getHeuristic().toString();
				case 3: return searchParameters.getInitialStateAsString();
				case 4: return searchParameters.getRandomSteps();
				case 5: return experiment.getSpaceSeedRange();
				case 6: return searchParameters.getCourseNumber();
				case 7: return searchParameters.getDrawLimit();
				case 8: return searchParameters.isBoundHeuristicCalls();
				
				// results
				case 9: return getStringValue(searchResults.getAverageCourseNumber(), experimentFinished); 
				case 10: return getStringValue(searchResults.getAverageFinalValue(), experimentFinished);
				case 11: return getStringValue(searchResults.getMaximumFinalValue(), experimentFinished);
				case 12: return getStringValue(searchResults.getMinimumFinalValue(), experimentFinished);
				case 13: return getStringValue(searchResults.getPercentageFinishedAllSteps(), experimentFinished);
				case 14: return getStringValue(searchResults.getAverageTotalStepsTaken(), experimentFinished);
			}
		}
		return null;
	}
	
	private String getStringValue(Double value, boolean dontReturnEmptyString)
	{
		if (dontReturnEmptyString)
		{
			return value.toString();
		}
		else
		{
			return "";
		}
	}
	
	
	@Override
	public int getColumnCount()
	{
		return COLUMN_NAMES.length;
	}

	@Override
	public String getColumnName(int columnIndex)
	{
		return COLUMN_NAMES[columnIndex];
	}

	@Override
	public int getRowCount()
	{
		return m_ExperimentsList.size();
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex)
	{
		return false;
	}

	public void add(List<Experiment> experiments)
	{
		m_ExperimentsList.addAll(experiments);
		fireTableDataChanged();
	}

	public void updateData()
	{
		fireTableDataChanged();
	}

	public TimeTable getTimeTable(int rowAtPoint)
	{
		return null;
//		ISearchAlgorithm<TimeTable> searchAlgorithm = m_SearchAlgorithmList.get(rowAtPoint);
//		return searchAlgorithm.getSearchResults().getFinalState().getState();
	}

	public void clear()
	{
		m_ExperimentsList.clear();
		updateData();
		
	}

}
